<template>
  <el-dialog
    :title="readonly ? `角色 ${role.roleName} 的权限` : `给角色 ${role.roleName} 赋予权限`"
    :visible.sync="visible"
    :close-on-click-modal="readonly"
    width="530px"
  >
    <el-alert
      type="info"
      :closable="false"
      style="margin-bottom: 16px;">
      <div slot="title">
        <span>你可以给角色赋予3种权限：</span>
        <span class="is-menu-node">菜单</span>
        <span class="el-icon-arrow-right"></span>
        <span class="is-page-node">页面</span>
        <span class="el-icon-arrow-right"></span>
        <span class="is-op-node">操作</span>
      </div>
    </el-alert>
    <el-tree
      ref="tree"
      :data="assignablePermissions"
      node-key="id"
      :props="{
        children: 'children',
        label: 'text'
      }"
      show-checkbox
      check-strictly
      :indent="24"
      style="height: 384px;overflow: auto;"
      v-loading="loading"
      @check="onCheck"
      v-slot="{data}"
    >
      <span
        class="el-tree-node__label"
        :class="data.isMenu ? (data.pagePath ? 'is-page-node' : 'is-menu-node') : 'is-op-node'">{{data.text}}</span>
    </el-tree>
    <el-alert
      type="info"
      :closable="false"
      style="margin-top: 8px;">
      <div slot="title" style="width:100%">
        {{`共 ${totalCount} 个权限节点，未选中 ${totalCount - checkedKeyCount} 个，已选中 ${checkedKeyCount} 个`}}
        <div v-if="!readonly" style="float:right;">
          <el-button type="text" style="padding: 0px;margin-left: 16px" @click="onClear">清空</el-button>
          <el-button type="text" style="padding: 0px;margin-left: 8px" @click="onSelectAll">全选</el-button>
          <el-button type="text" style="padding: 0px;margin-left: 8px" @click="onRestore">重置</el-button>
        </div>
      </div>
    </el-alert>
    <span v-show="!readonly" slot="footer">
      <el-button type="primary" @click="onSubmit">确定</el-button>
      <el-button type="default" @click="visible = false">取消</el-button>
    </span>
  </el-dialog>
</template>

<script>
export default {
  data() {
    return {
      visible: false,
      readonly: false,
      role: {},
      loading: true,
      assignablePermissions: [],
      checkedKeyCount: 0,
    };
  },
  computed: {
    totalCount() {
      return count(this.assignablePermissions);
      function count(nodes) {
        let n = nodes.length;
        nodes.forEach(node => {
          if (node.children)
            n += count(node.children);
        });
        return n;
      }
    }
  },
  mounted() {
    this.assignablePermissions = admin.permissions;
  },
  methods: {
    async open(role, readonly) {
      this.visible = true;
      this.role = role;
      this.readonly = !!readonly;
      this.loading = true;
      this.permissions = await this.$http.get('/api/role/permissions', {params: {id: role.id}});
      this.$refs.tree.setCheckedKeys(this.permissions);
      this.checkedKeyCount = this.permissions.length;
      this.loading = false;
    },
    onCheck(node, checkedState) {
      this.checkedKeyCount = checkedState.checkedKeys.length;
    },
    onClear() {
      this.$refs.tree.setCheckedKeys([]);
      this.checkedKeyCount = 0;
    },
    onRestore() {
      this.$refs.tree.setCheckedKeys(this.permissions);
      this.checkedKeyCount = this.permissions.length;
    },
    onSelectAll() {
      this.$refs.tree.setCheckedKeys(getKeys(this.assignablePermissions));
      function getKeys(nodes) {
        let keys = [];
        nodes.forEach(node => {
          keys.push(node.id);
          if (node.children)
            keys = keys.concat(getKeys(node.children));
        });
        return keys;
      }
    },
    async onSubmit() {
      const ret = await this.$http.post(
        '/api/role/permissions',
        {roleId: this.role.id, permissions: this.$refs.tree.getCheckedKeys()},
        {dataType: 'json'});
      if (ret.success) {
        this.role.permissionCount = this.checkedKeyCount;
        this.$message.success(ret.message);
        this.visible = false;
      }
    }
  }
}
</script>

<style scoped>
.el-alert >>> .el-alert__content {
  width: 100%;
}

.is-menu-node {
  color: #606266;
}
.is-page-node {
  color: #E6A23C;
}
.is-op-node {
  color: #F56C6C;
}
</style>